<template>
  <el-upload
    ref="uploadIns"
    v-model:file-list="files"
    :auto-upload="false"
    :on-change="handleChange"
    :before-upload="importBefore"
    v-bind="$attrs"
  >
    <slot></slot>
  </el-upload>
</template>

<script name="Upload" lang="ts" setup>
  import { computed, ref, type PropType } from 'vue';
  import {
    ElMessage,
    type UploadInstance,
    type UploadProps
  } from 'element-plus';
  import { getStorage } from '@/utils/cache';
  import { UPLOAD_URL } from '@/constants/common';
  import axios from 'axios';

  const props = defineProps({
    accept: {
      type: Array,
      default: () => []
    },
    fileList: {
      type: Array as PropType<Array<IFileType>>,
      default: () => []
    }
  });

  const emits = defineEmits(['update:fileList']);

  const files = computed({
    get() {
      return props.fileList;
    },
    set(list: Array<IFileType>) {
      emits('update:fileList', list);
    }
  });

  const uploadIns = ref<UploadInstance>();

  const handleChange: UploadProps['onChange'] = (file, fileList) => {
    const type = file.name.split('.');
    const suffix = type[type.length - 1];
    if (!props.accept.includes(suffix)) {
      ElMessage.error('不支持当前格式上传!');
      fileList.splice(fileList.length - 1, 1);
      return;
    }
    if (file.size && file.size / 1024 / 1024 > 2) {
      ElMessage.error('上传文件大小不能超过 2MB!');
      fileList.splice(fileList.length - 1, 1);
      return;
    }
  };

  const importBefore: UploadProps['beforeUpload'] = (rawFile) => {
    const flieArr = rawFile.name.split('.');
    const suffix = flieArr[flieArr.length - 1];
    if (!props.accept.includes(suffix)) {
      ElMessage.error('不支持当前格式上传!');
      return false;
    }
    if (rawFile.size / 1024 / 1024 > 2) {
      ElMessage.error('上传文件大小不能超过 2MB!');
      return false;
    }
    return true;
  };

  const uploadByAxiox = async (
    file: IFileType,
    params: Record<string, any>
  ): Promise<string> => {
    try {
      file.status = 'uploading';
      const Token = getStorage<string>('token');
      const formData = new FormData();
      formData.append('file', file.raw!);
      const resp = await axios.post(UPLOAD_URL, formData, {
        headers: {
          'Content-Type': 'application/form-data',
          Authorization: `Bearer ${Token}`
        },
        params
      });
      file.status = 'success';
      return Promise.resolve(resp.data.Data.Url);
    } catch (error) {
      file.status = 'fail';
      return Promise.reject(error);
    }
  };

  defineExpose({
    async submit(params: Record<string, any>) {
      const tasks: Promise<string>[] = [];
      for (const file of files.value) {
        if (file.isRWrite) {
          tasks.push(Promise.resolve(file.url || ''));
        } else {
          tasks.push(uploadByAxiox(file, params));
        }
      }
      return Promise.all(tasks);
    }
  });
</script>
